using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;
using WiMo.Games.Drawables;
using System.Collections;

namespace WiMo.Games.Display.WP7S.XNA
{
    public class DisplayManager : IDisplay
    {
        IGameEngine _gameEngine;
        GraphicsDevice _graphicsDevice;
        SpriteBatch _spriteBatch;
        List<WiMo.Games.Drawables.IDrawable> _sprites;
        List<WiMo.Games.Drawables.IDrawable> _tempObjects;

        public DisplayManager(IGameEngine gameEngine, Size targetSize, Size bounds)
        {
            _gameEngine = gameEngine;
            _sprites = new List<WiMo.Games.Drawables.IDrawable>();
            _tempObjects = new List<IDrawable>();

            ScaleFactor = new Vector2((float)bounds.Width / (float)targetSize.Width, (float)bounds.Height / (float)targetSize.Height);
            TargetSize = targetSize;
            Size = bounds;
            DisplayOffset = Location.Empty;
            DisplayStrategy = DisplayStrategies.Automatic;
        }

        public byte AspectRatio { get; set; }
        public int DPI { get; set; }
        public string Name { get; private set; }
        public Color BackgroundColor { get; set; }
        public Size Size { get; private set; }
        public Size TargetSize { get; private set; }
        public Vector2 ScaleFactor { get; private set; }
        public bool Diagnostics { get; set; }
        public ITexture BackgroundImage { get; set; }
        public DisplayStrategies DisplayStrategy { get; set; }

        public Location DisplayOffset { get; set; }

        public void Reset()
        {
            throw new NotImplementedException();
        }

        public void Add(IDrawable drawable)
        {
            _sprites.Add(drawable);
        }

        public ISpriteLine DrawLine(Location start, Location end, Color color, int width)
        {
            var line = new Drawables.SpriteLine();
            line.Scale = ScaleFactor;
            line.Start = start;
            line.End = end;
            line.LineColor = color;
            line.Width = width;
            line.IsTransient = true;

            _sprites.Add(line);
            _tempObjects.Add(line);

            return line;
        }

        public ISpriteText DrawText(PointF position, string text, ISpriteFont font, Color foreColor)
        {
            return DrawText(position, text, font, foreColor, Origin.TopLeft);
        }

        public ISpriteText DrawText(PointF position, string text, ISpriteFont font, Color foreColor, Origin origin)
        {
            var spriteText = new Drawables.SpriteText();
            spriteText.Scale = ScaleFactor;
            spriteText.Position = position;
            spriteText.Text = text;
            spriteText.Font = font;
            spriteText.ForeColor = foreColor;
            spriteText.Origin = origin;

            spriteText.IsTransient = true;
            _sprites.Add(spriteText);
            _tempObjects.Add(spriteText);

            return spriteText;
        }

        public ISpriteShape DrawRectangle(Rectangle rect, Color color, int width)
        {
            return DrawRectangle(rect, color, width, Origin.Center);
        }

        public ISpriteShape DrawRectangle(Rectangle rect, Color color, int width, Origin origin)
        {
            var shape = new Drawables.SpriteShape();
            shape.Scale = ScaleFactor;
            shape.ShapeType = ShapeType.Rectangle;
            shape.Rect = rect;
            shape.BorderColor = color;
            shape.BorderWidth = width;
            shape.Origin = origin;

            shape.IsTransient = true;
            _sprites.Add(shape);
            _tempObjects.Add(shape);

            return shape;
        }

        public ISpriteShape FillRectangle(WiMo.Games.Rectangle rect, Color fillColor, Color borderColor, int width)
        {
            return FillRectangle(rect, fillColor, borderColor, width, Origin.Center);
        }

        public ISpriteShape FillRectangle(WiMo.Games.Rectangle rect, Color fillColor, Color borderColor, int width, Origin origin)
        {
            var shape = new Drawables.SpriteShape();
            shape.Scale = ScaleFactor;
            shape.ShapeType = ShapeType.Rectangle;
            shape.Rect = rect;
            shape.FillColor = fillColor;
            shape.BorderColor = borderColor;
            shape.BorderWidth = width;
            shape.Origin = origin;

            shape.IsTransient = true;
            _sprites.Add(shape);
            _tempObjects.Add(shape);

            return shape;
        }

        public ISpriteShape DrawCircle(PointF position, int radius, Color borderColor, int width)
        {
            var circle = new Drawables.SpriteShape();
            circle.Scale = ScaleFactor;
            circle.ShapeType = ShapeType.Ellipse;
            circle.Size = new Size(radius * 2, radius * 2);
            circle.Position = position;
            circle.BorderWidth = width;
            circle.BorderColor = borderColor;

            circle.IsTransient = true;
            _sprites.Add(circle);
            _tempObjects.Add(circle);

            return circle;

        }

        public ISpriteShape FillCircle(PointF position, int radius, Color fillColor, Color borderColor, int width)
        {
            var circle = new Drawables.SpriteShape();
            circle.Scale = ScaleFactor;
            circle.ShapeType = ShapeType.Ellipse;
            circle.Size = new Size(radius * 2, radius * 2);
            circle.FillColor = fillColor;
            circle.BorderColor = borderColor;
            circle.BorderWidth = width;
            circle.Position = position;
            circle.Origin = Origin.Center;
            circle.IsTransient = true;

            circle.IsTransient = true;
            _sprites.Add(circle);
            _tempObjects.Add(circle);

            return circle;
        }

        public void Render(ISpriteImage sprite)
        {
            //throw new NotImplementedException();
        }

        public void Render(ISpriteText text)
        {
            //throw new NotImplementedException();
        }

        public void Render(ISpriteShape shape)
        {
            //   throw new NotImplementedException();
        }

        public void Render(ISpriteLine line)
        {
            // throw new NotImplementedException();
        }

        public void Render()
        {
            if (_graphicsDevice == null)
            {
                _graphicsDevice = _gameEngine.GraphicsManager as GraphicsDevice;
                if (_graphicsDevice == null)
                    throw new NullReferenceException("When using the ZuneHD display manager, the GameEngine must expose XNA's Game.GraphicsDevice property as GraphicsManager.");

                _spriteBatch = new SpriteBatch(_graphicsDevice);
            }

            _graphicsDevice.Clear(BackgroundColor.GetXNAColor());

            //_spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
            _spriteBatch.Begin();

            if (BackgroundImage != null)
            {
                var texture = BackgroundImage.TextureInformation as Texture2D;
                var dest = new Microsoft.Xna.Framework.Rectangle(0, 0, Size.Width, Size.Height);
                _spriteBatch.Draw(texture,dest,Microsoft.Xna.Framework.Color.White);
            }

            foreach (var sprite in _sprites)
            {
                var text = sprite as ISpriteText;
                if (text != null && text.IsVisible)
                {
                    if (sprite.Origin == Origin.Center)
                    {
                        Microsoft.Xna.Framework.Graphics.SpriteFont font = text.Font.FontInformation as Microsoft.Xna.Framework.Graphics.SpriteFont;
                        var fontOffset = font.MeasureString(text.Text);

                        _spriteBatch.DrawString(font, text.Text, sprite.Position.GetXNAVector2() - fontOffset / 2, text.ForeColor.GetXNAColor());
                    }
                    else
                        _spriteBatch.DrawString(text.Font.FontInformation as Microsoft.Xna.Framework.Graphics.SpriteFont, text.Text, sprite.Position.GetXNAVector2(), text.ForeColor.GetXNAColor());
                }
                else
                {
                    var spriteImage = sprite as ISpriteImage;
                    if (spriteImage != null && spriteImage.IsVisible)
                    {
                        var topLeft = (sprite.Origin == Origin.TopLeft) ? new Location(sprite.Position.X, sprite.Position.Y) : new Location(sprite.Position.X - sprite.Size.Width / 2, sprite.Position.Y - sprite.Size.Height / 2);
                        var destRect = new Microsoft.Xna.Framework.Rectangle(topLeft.X, topLeft.Y, spriteImage.Size.Width, spriteImage.Size.Height);
                        _spriteBatch.Draw(spriteImage.TextureList[spriteImage.ImageIndex].TextureInformation as Texture2D, destRect, Microsoft.Xna.Framework.Color.White);
                    }
                    else
                    {
                        var spriteShape = sprite as ISpriteShape;
                        if (spriteShape != null && spriteShape.IsVisible)
                            Drawables.WiMoTexture.DrawShape(_spriteBatch, spriteShape);
                    }
                }
            }

            _spriteBatch.End();

            foreach (var temp in _tempObjects)
            {
                temp.Dispose();
            }

            _sprites.Clear();
            _tempObjects.Clear();
        }

        public ISpriteShape CreateRectangle()
        {
            return new Drawables.Rectangle();
        }

        public ISpriteShape CreatePolygon()
        {
            return new Drawables.Polygon();
        }

        public ISpriteImage CreateSpriteImage()
        {
            return new Drawables.SpriteImage();
        }

        public ISpriteLine CreateLine()
        {
            return new Drawables.SpriteLine(); 
        }

        public ISpriteShape CreateLineList()
        {
            return new Drawables.Linelist();
        }

        public ISpriteShape CreateEllipse()
        {
            return new Drawables.Ellipse();
        }

        public ISpriteText CreateText()
        {
            return new Drawables.SpriteText();
        }

        public void Invalidate()
        {
        }

        public void Resize(Size bounds)
        {
        
        }

        public void Dispose()
        {
       
        }
    }
}
